#ifndef HSE_HSE_COMMON_H
#define HSE_HSE_COMMON_H

#include <string>
#include <hash_map>
#include <math.h>

namespace hse {
using std::string;
using stdext::hash_compare;

/**
 * Declare this in PRIVATE area to
 */
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
            TypeName(const TypeName&); \
            void operator=(const TypeName&)
#define MAX_TERM_LEN 64
#define MAX_TOKEN_LEN 10
#define FILE_INDEX "index"
#define FILE_POSTING "posting"
#define FILE_META "meta"
#define DOC_INFO "docinfo"
#define BLOCK_SIZE 4096

#define DEBUG_F(x) 
#define LOG_DEBUG(x) 
#define LOG_INFO(x) x
#define LOG_WARN(x) x
#define LOG_ERROR(x) x
#define F_EPSILON 1e-6
#define MAX_CONTENT_LEN 200

#define BM25_b 0.75
#define BM25_k1 1.2
#define BM25_k2 100
#define BM25_qf 0
#define BM25_miss_weight 100
#define BM25_miss_factor 1.0 //a doc at least include BM25_miss_factor*token_size term, 1 means all query

const double BM25_k2_factor = log( ((double)(BM25_k2+1)*BM25_qf/(BM25_k2 + BM25_qf)) );

typedef unsigned char hse_byte_t;

inline bool string_less(const string *s1, const string *s2) {
	return s1->compare(*s2) < 0;
}

class StringLess : public std::binary_function<string , string , bool> {
public:
	inline bool operator()(const string s1, const string s2) const {
		return string_less(&s1, &s2);
	}
};


class  StringHashCompare : public hash_compare<string*, StringLess> {
public:
	inline size_t operator()(const string *s) const {
		// hash range of elements
		size_t v = 2166136261U;
		for(size_t i = 0 ; i < s->size() ; i++)
			v = 16777619U * v ^ (size_t)(*s)[i];
		// hash _Keyval to size_t value by pseudorandomizing transform
		long _Quot = v & LONG_MAX;
		ldiv_t _Qrem = ldiv(_Quot, 127773);

		_Qrem.rem = 16807 * _Qrem.rem - 2836 * _Qrem.quot;
		if (_Qrem.rem < 0)
			_Qrem.rem += LONG_MAX;
		return ((size_t)_Qrem.rem);
	}

	inline bool operator()(const string *s1, const string *s2) const {
		return string_less(s1, s2);
	}
};

/**
 * return -1 if not find
 */
int string_term_find(string& src, string& lowercased_find, int npos);

string string_term_em(string& src, std::vector<string>& terms);

} //end of namespace

#endif